/*
 * SiFiSy - A File System Simulator
 * Copyright (C) 2010  SevenSoft
 *
 * This file is part of SiFiSy.
 *
 * SiFiSy is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * SiFiSy is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with SiFiSy.  If not, see <http://www.gnu.org/licenses/>.
 */

package sifisy.newgui;

import java.awt.*;
import javax.swing.*;
import sifisy.core.Model;

/**
 * @author Alberto Longato
 * @version %I%, %G%
 * @createData 12/05/2010
 */
public class FatSchema extends JPanel {
    private int simId;

    public FatSchema(int simId){
        this.simId = simId;
    }


    public void FillHD(Graphics g, int x, int y, int lenx, int leny, int averageBlocks) {
     g.setColor(Color.cyan);
     for(int i=0;i<averageBlocks; i++){
         g.setColor(Color.cyan);
         g.fillRect(x+(i*lenx), y , lenx , leny );
        x++;
        }
    }

    public int FillFAT(Graphics g, int x, int y, int lenx, int leny, int averageBlocks,
            int xfat, int yfat, int lenxfat, int lenyfat) {

      g.setColor(Color.cyan);
      for(int i=0; i<averageBlocks; i++){
          if( xfat > 402){
            yfat=yfat+lenyfat;
            xfat=101;
          }
      g.fillRect(xfat, yfat+(6*lenyfat+lenyfat/2)+1 , lenxfat-1 , lenyfat-1);
      xfat=xfat+lenxfat;

      }
      xfat=xfat+lenxfat;
return xfat;
}

    public void DrawHandwriting(Graphics g, int x, int y, int lenx, int leny, String nomefile, int[] File,
            int xfat, int yfat, int lenxfat, int lenyfat){
        boolean point=false;
        xfat++;
        int start =0;
        int empty= lenx;

        int averageBlocks = File[2];
       //se i blocchi contigui son maggiori di 5, ne indico 5 e ci scrivo che son di piu
        if(averageBlocks>5)
            averageBlocks= 5;

        int len = (lenx*averageBlocks)-10;
        int fatlen = (lenxfat*averageBlocks)+lenxfat;

        //se sforo i 25 blocchi fisici che ho nel disegno della partizione
        while( ((averageBlocks+(empty/lenx))* File[3]) > 25) {
            File[3]--;
            point =true;
        }

        String exp= "KB";
        if(File[1]== 20) exp= "MB";
        if(File[1]== 30) exp= "GB";

        for(int i=0; i< File[3]; i++)
        {
         g.setColor(Color.black);
         g.drawLine(x+start, y, x+5+start, y+5);
         g.drawLine(x+5+len+start, y+5, x+10+len+start, y);
         g.drawLine(x+5+start, y+5, x+5+len+start, y+5);
         g.setColor(Color.blue);
         
         g.drawString(nomefile, ((((x+5)+(x+5+len))/2)-6)+start, y+15 );
         g.drawString("" + File[2] + " block", ((((x+5)+(x+5+len))/2)-18)+start, y+25 );
         g.drawString("da " + File[0] + " " + exp + "", ((((x+5)+(x+5+len))/2)-18)+start, y+35 );
         g.setColor(Color.red);
         g.drawString("TOT " + File[0]*File[2] + " " +exp, ((((x+5)+(x+5+len))/2)-20)+start, y+45 );
                  
         FillHD(g, x+1+start,y-79,19,79,averageBlocks);
         int oldxfat=xfat;
         xfat = FillFAT(g, x+1+start,y-79,19,79,averageBlocks, xfat, yfat, lenxfat, lenyfat);
         if(oldxfat>xfat) //son andato accapo a meta'
             yfat=yfat+lenyfat;

         start= start+(len+10)+empty;

         //vado accapo giusto
         if(xfat >= 402){
              xfat=101;
             yfat=yfat+lenyfat;
         }

        }
        // °°°
        g.setColor(Color.blue);
        if(point)
         g.drawString("° ° °", ((((x+5)+(x+5+len))/2)-18)+start, y+25 );
    }

    public void insertFile(Graphics g, int x, int y, int lenx, int leny, String nomefile, int[] File,
            int xfat, int yfat, int lenxfat, int lenyfat){
        DrawHandwriting(g,x,y,lenx,leny,nomefile, File, xfat,yfat,lenxfat,lenyfat);
    }

    public void drawRowLegend(Graphics g, Color c, String desc, int x, int y, int x1, int y1){
        g.setColor(Color.blue);
        g.drawRect(x + 20, y , x1 , y1 );
        g.setColor(c);
        g.fillRect(x + 21, y + 1, x1-1 , y1-1 );
        g.setColor(Color.black);
        g.drawString("" + desc + "", x + 50, y +y1-1);
    }

    public void drawLegend(Graphics g, int x, int y, String nomefile){
        g.setColor(Color.orange);
        g.drawRect(x , y , 130 , 105 );
        g.fillRect(x , y , 130 , 105 );
        g.setColor(Color.red);
        y=y+10;
        g.drawString("LEGENDA", x + 45, y );
        int x1=25; int y1=10;

        y=y+10;
        Color c= new Color(0,255,0);
        String desc= "Blocchi gia' pieni";
        drawRowLegend(g, c, desc, x, y, x1,y1);

        y=y+25;
        c= new Color(255,255,255);
        desc= "Blocchi liberi";
        drawRowLegend(g, c, desc, x, y, x1,y1);

        y=y+25;
        c= new Color(0,255,255);
        desc= "Blocchi occupati";
        drawRowLegend(g, c, desc, x, y, x1,y1);
        g.drawString("da: ", x + 50, y +(2*y1)-1);
        g.drawString("" + nomefile + "", x + 50, y +y1+19);
    }

    public void drawHD(Graphics g, int length, int x, int y, int lenx, int leny){
        g.setColor(Color.blue);
        g.drawString("Partizione:", x+250 , y-5);
        for (int i=0; i<length; i++)
            g.drawRect(x+(i*lenx), y , lenx , leny );
        //Occupo i primi
        g.setColor(Color.green);
        for (int i=0; i<3; i++)
            g.fillRect(x+(i*lenx)+1, y +1, lenx-1 , leny-1 );
        g.setColor(Color.red);
        String nb = "N.B. I Primi blocchi (cluster) della partizione sono occupati dalla FAT " +
                "e da dati di sistema";
        g.drawString(nb, x, y+150);

        nb = "I primi n blocchi azzurri contigui della Fat corrisopondono ai primi nella partizione. i secondi" +
                " ai secondi e cosi' via";
        g.drawString(nb, x, y+175);

        nb = "I blocchi bianchi tra quelli occupati dal file son da considerare pieni al momento del salvataggio del file";
        g.drawString(nb, x, y+200);
    }

    public void drawFat(Graphics g, int length, int x, int y, int lenx, int leny, String nomefile){
        // length è il numero dei cluster (1 puntatore : 1 cluster)
        Font font = new Font(Font.SANS_SERIF, Font.BOLD, 9);
        g.setFont(font);
        g.setColor(Color.blue);
        g.drawString("Fat32:", x -70+250, y-20);

        // Scrivo nome alle colonne
        for(int i=0; i < 10; i++)
            g.drawString("0" + i +"", x + i*(lenx)+5 , y-2 );
        g.drawString("0A", x + (10*lenx)+5 , y-2 );
        g.drawString("0B", x + (11*lenx)+5 , y-2 );
        g.drawString("0C", x + (12*lenx)+5 , y-2 );
        g.drawString("0D", x + (13*lenx)+5 , y-2 );
        g.drawString("0E", x + (14*lenx)+5 , y-2 );
        g.drawString("0F", x + (15*lenx)+5 , y-2 );
        // Disegno Griglia
        // Primo pezzo
        for(int j=0; j < 4; j++){
         g.drawString("0x00:   0x" + j +"0", x - 70 , y + (j*leny) + leny );
            for(int i=0; i < 16; i++){
                g.drawRect(x + i*(lenx), y + (j*leny) , lenx , leny );
                g.setColor(Color.green);
                g.fillRect(x + i*(lenx) + 1, y + (j*leny) + 1, lenx -1, leny -1);
                g.setColor(Color.blue);
            }
        }
        //Secondo pezzo (...)
        y=y+5*leny;
        for(int j=0; j < 2; j++){
            for(int i=0; i < 16; i++)
                g.drawString("° ° °", x+ i*(lenx) + 2, y + (j*leny) );
        }
        //Terzo pezzo
        y=y+2*leny - (leny/2);
        for(int j=0; j < 8; j++){
          g.drawString("0x0C:   0x" + j +"0", x - 70 , y + (j*leny) + leny );
            for(int i=0; i< 16; i++)
                    g.drawRect(x+ i*(lenx), y + (j*leny) , lenx , leny );
        }
        //Quarto pezzo (...)
        y=y+9*leny;
        for(int j=0; j < 2; j++){
            for(int i=0; i < 16; i++)
                g.drawString("° ° °", x+ i*(lenx) + 2, y + (j*leny) );
        }
        //Quinto pezzo
        y=y+2*leny - (leny/2);
        for(int j=0; j < 2; j++){
            for(int i=0; i< 16; i++)
                    g.drawRect(x+ i*(lenx), y + (j*leny) , lenx , leny );
        }
        g.drawString("0xFF:   0xEF", x - 70 , y +  leny );
        g.drawString("0xFF:   0xFF", x - 70 , y + (2*leny) );
        y=y+2*lenx;
        //Legenda
        drawLegend(g, 450, 50, nomefile);
        //Scritta
        g.setColor(Color.red);
        String nb = "N.B. I Primi settori della FAT sono riservati per il " +
                "settore di avvio, BIOS Parameter Block e informazione del FS";
        g.drawString(nb, x - 70, y);

        //quadrato nero
        g.setColor(Color.black);
        g.fillRect(x-72, y-250, 560, 2);
        g.fillRect(x-72, y-250, 2, 260);
        g.fillRect(x-72, y+10, 560, 2);
        g.fillRect(x-72+560, y-250, 2, 262);

        //Partizione
        y=y+7*leny;
        g.drawLine(x-50, y, x-72, y-60);
        g.drawLine(x-30, y, x+489, y-60);
        lenx=20;
        leny=80;

        drawHD(g, length, x-70, y, lenx, leny);
    }

 public void insertRem(Graphics g, int x, int y,int lenx,int leny, int toAdd, String nomefile, int[] File,
                int xfat, int yfat, int lenxfat, int lenyfat){
     xfat++;
     int start =0;
     int averageBlocks = toAdd;
             
     FillHD(g, x+1+start,y-79,19,79,averageBlocks);
     xfat = FillFAT(g, x+1+start,y-79,19,79,averageBlocks, xfat, yfat, lenxfat, lenyfat);
}

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        int xfat = 100, yfat = 50, lenxfat = 20, lenyfat = 10;
        int x = 100, y = 50, lenx = 20, leny = 10;
        int length = 28;

        //files
        //NB dimension è la dimensione del cluster
        //Exponent è l'esponente del cluster
        int totalBlockFile = (int) (Model.getSimulation(0).getFiles().elementAt(0).getSize() / (Model.getBlockDimension(0) * Math.pow(2, Model.getBlockExponent(0))));
               
        int numerator = (int)Model.getSimulation(0).getFiles().elementAt(0).getSize();
        int denominator = (int)(Model.getBlockDimension(0) * Math.pow(2, Model.getBlockExponent(0)));
        int toAdd = (numerator%denominator)/(int)Math.pow(2, Model.getBlockExponent(0));
        if(toAdd > 0)
            toAdd=1;
   
       
        int mem=totalBlockFile+toAdd;
        int dimension= Model.getBlockDimension(simId);          //dim cluster
        int exponent = Model.getBlockExponent(simId);          // esponente del cluster
        int averageBlocks = (int)Model.getSimulation(simId).getFiles().elementAt(0).getAverageBlocks();
        int part = totalBlockFile/averageBlocks; //numero di parti contigue che formano il file
        
        String nomefile=""+ Model.getSimulation(simId).getFiles().elementAt(0).getId();
        int File[]={dimension,exponent,averageBlocks, part};

        drawFat(g, length , x,y,lenx,leny, nomefile);
        insertFile(g,x-lenx/2,y+36*leny,lenx,leny, nomefile,File,
                xfat, yfat, lenxfat, lenyfat);
        //se ho pezzetti rimanenti
        insertRem(g,x-lenx/2,y+36*leny,lenx,leny, (totalBlockFile%averageBlocks)+toAdd, nomefile, File,
                xfat, yfat+lenyfat, lenxfat, lenyfat);

        
        g.setColor(Color.black);
        g.drawString("Ci sono i totale "+totalBlockFile+" blocchi", 450, 180 );
        if(totalBlockFile>averageBlocks)
            g.drawString("contigui a gruppi di "+averageBlocks, 450, 200 );
        else
            g.drawString("contigui indirizzati", 450, 200 );
        if( (totalBlockFile%averageBlocks) > 0)
              g.drawString("ed infine "+((totalBlockFile%averageBlocks)+toAdd)+" blocchi", 450, 220 );
        if( toAdd > 0)
              g.drawString("L'ultimo occupato in parte", 450, 240 );
        }

       
    

    /*
    public static void main(String[] args) {
        FatSchema disegno = new FatSchema(simId);
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(disegno);
        f.setSize(700, 600);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
     */
}